#include "newfs.h"

/******************************************************************************
* SECTION: 宏定义
*******************************************************************************/
#define OPTION(t, p)        { t, offsetof(struct custom_options, p), 1 }
#define EXT2_BlkSize (1024)
#define ERROR_NO (-1)
/******************************************************************************
* SECTION: 全局变量
*******************************************************************************/
static const struct fuse_opt option_spec[] = {		/* 用于FUSE文件系统解析参数 */
	OPTION("--device=%s", device),
	FUSE_OPT_END
};
struct newfs_super_m super_m;	
struct custom_options newfs_options;			 /* 全局选项 */
				//全局主存超级块
/******************************************************************************
* SECTION: FUSE操作定义
*******************************************************************************/
static struct fuse_operations operations = {
	.init = newfs_init,						 /* mount文件系统 */		
	.destroy = newfs_destroy,				 /* umount文件系统 */
	.mkdir = newfs_mkdir,					 /* 建目录，mkdir */
	.getattr = newfs_getattr,				 /* 获取文件属性，类似stat，必须完成 */
	.readdir = newfs_readdir,				 /* 填充dentrys */
	.mknod = newfs_mknod,					 /* 创建文件，touch相关 */
	.write = newfs_write,								  	 /* 写入文件 */
	.read = newfs_read,								  	 /* 读文件 */
	.utimens = newfs_utimens,				 /* 修改时间，忽略，避免touch报错 */
	.truncate = newfs_truncate,						  		 /* 改变文件大小 */
	.unlink = NULL,							  		 /* 删除文件 */
	.rmdir	= NULL,							  		 /* 删除目录， rm -r */
	.rename = NULL,							  		 /* 重命名，mv */

	.open = NULL,							
	.opendir = NULL,
	.access = NULL
};

/*********************************************
				封装函数实现
*********************************************/
/**
 * @brief 封装ddriver的读,一次读1024B
 *
 * @param offset 要读的数据在磁盘上的偏移
 * @param out_content 读出的数据首地址放到out_content
 * @param size 要读出的数据大小(字节)
 * @return int
 */
int newfs_driver_read(int offset, uint8_t *out_content, int size) {
	//将偏移按IOsize内存对齐
    int      offset_aligned = MYFS_ROUND_DOWN(offset,EXT2_BlkSize);
    int      bias           = offset - offset_aligned;
    int      size_aligned   = MYFS_ROUND_UP((size + bias), EXT2_BlkSize);
    //分配的内存按EXT2的数据块大小对齐
	uint8_t* temp_content   = (uint8_t*)malloc(size_aligned);
    uint8_t* cur            = temp_content;
   //移动磁头到指定数据位置
    ddriver_seek(MYFS_DRIVER(), offset_aligned, SEEK_SET);
    while (size_aligned != 0) //每个循环读1024B
    {
        ddriver_read(MYFS_DRIVER(), cur, MYFS_IO_SZ());  
		ddriver_read(MYFS_DRIVER(),cur + MYFS_IO_SZ(),MYFS_IO_SZ());
        cur          += EXT2_BlkSize;			//EXT2_BlkSize为1024
        size_aligned -= EXT2_BlkSize;   
    }
    memcpy(out_content, temp_content + bias, size);
    free(temp_content);
    return MYFS_ERROR_NONE;
}

/**
 * @brief 写入数据
 * 
 * @param fd ddriver设备handler
 * @param buf 要写入的数据Buf
 * @param size 要写入的数据大小
 * @return int 0成功，否则失败
 */
int newfs_driver_write(int offset, uint8_t *in_content, int size) {
    int      offset_aligned = MYFS_ROUND_DOWN(offset, EXT2_BlkSize);
    int      bias           = offset - offset_aligned;
    int      size_aligned   = MYFS_ROUND_UP((size + bias), EXT2_BlkSize);
    uint8_t* temp_content   = (uint8_t*)malloc(size_aligned);
    uint8_t* cur            = temp_content;
	//为防止bias所指区域的内容被覆盖，需先读出相关内容，再用in_content覆盖部分
    newfs_driver_read(offset_aligned, temp_content, size_aligned);		
    memcpy(temp_content + bias, in_content, size);
    
    ddriver_seek(MYFS_DRIVER(), offset_aligned, SEEK_SET);
    while (size_aligned != 0)
    {
        ddriver_write(MYFS_DRIVER(), cur, MYFS_IO_SZ());
		ddriver_write(MYFS_DRIVER(), cur + MYFS_IO_SZ(), MYFS_IO_SZ());
        cur          += EXT2_BlkSize;
        size_aligned -= EXT2_BlkSize;   
    }

    free(temp_content);
    return MYFS_ERROR_NONE;
}

/**
 * @brief 为目录项dentry创建一个inode
 * 
 * @param dentry ddriver设备handler
 * @return 返回指向新建inode的指针
 */
struct newfs_inode_m* newfs_alloc_inode(struct newfs_dentry_m * dentry)
{
	struct newfs_inode_m* inode;
    int byte_cur = 0; 
    int bit_cur  = 0; 
	int ino_count = 0;
    int data_byte_idx = 0;
    int data_bit_idx  = 0;
    boolean find = FALSE;

    for (byte_cur = 0; byte_cur < MYFS_BLKS_SZ(super_m.map_inode_blks);byte_cur++)
	{
		for(bit_cur = 0; bit_cur < UINT8_BITS ; bit_cur++)
		{
			if((super_m.map_inode[byte_cur] & (0x1<<bit_cur)) == 0)
			{
				super_m.map_inode[byte_cur] = super_m.map_inode[byte_cur] | (0x1<<bit_cur);
				find  = TRUE;
				break;
			}
			ino_count++;
		}
		if(find) 	break;
		
	}
    

    if (!find || ino_count >= super_m.max_ino)
        return NULL;
		// return -MYFS_ERROR_NOSPACE;
   
    //将数据位图相应位置为1
    data_byte_idx = (ino_count * MYFS_BLK_PER_FILE * 2) / UINT8_BITS;
    data_bit_idx = (ino_count * MYFS_BLK_PER_FILE * 2) % UINT8_BITS;
    //循环12次(一个文件12个512B)
    for(int i = 0 ; i < MYFS_BLK_PER_FILE * 2; i++){
        super_m.map_data[data_byte_idx] = super_m.map_data[data_byte_idx] | (0x1<<data_bit_idx);
        data_bit_idx = ++data_bit_idx % UINT8_BITS ;
        data_byte_idx = (data_bit_idx == 0)?(data_byte_idx + 1):data_byte_idx;
    }


    inode = (struct newfs_inode_m*)malloc(sizeof(struct newfs_inode_m));
    inode->ino  = ino_count; 
    inode->size = 0;
                                                      /* dentry指向inode */
    dentry->inode = inode;
    dentry->ino   = inode->ino;
                                                      /* inode指回dentry */
    inode->dentry = dentry;
    
    inode->dir_cnt = 0;
    inode->dentrys = NULL;							//起始目录项为空
    
	//如果是inode指向的是数据，则为它分配数据区域
    if (MYFS_IS_REG(inode)) {
        inode->data = (uint8_t *)malloc(MYFS_BLKS_SZ(2 * MYFS_BLK_PER_FILE));
    }

    return inode;
}
/**
 * @brief 将内存中的inode写回相应到磁盘的inode
 * 
 * @param inode 
 * @return int 
 */
int newfs_sync_inode_d(struct newfs_inode_m * inode)
{
	struct newfs_inode  inode_d;
    inode_d.ino         = inode->ino;
    inode_d.size        = inode->size;
    inode_d.ftype       = inode->dentry->ftype;
    inode_d.dir_cnt     = inode->dir_cnt;
	if (newfs_driver_write(MYFS_INO_OFS(inode->ino), (uint8_t *)&inode_d, 
                     sizeof(struct newfs_inode)) != MYFS_ERROR_NONE) {
        return -MYFS_ERROR_IO;
    }
	return MYFS_ERROR_NONE;
}
/**
 * @brief 将内存inode及其内容中所有结构全部刷回磁盘
 * 
 * @param inode 
 * @return int 
 */
int newfs_sync_inode(struct newfs_inode_m * inode) {
    
    struct newfs_dentry_m*  dentry_cur;
    struct newfs_dentry     dentry_d;
    int ino             = inode->ino;
    int offset;
	//写回相应磁盘上的inode
    newfs_sync_inode_d(inode);
    

	if (MYFS_IS_REG(inode)) {			//如果是file类型，则写回数据块
		if (newfs_driver_write(MYFS_DATA_OFS(ino), inode->data, 
								MYFS_BLKS_SZ(MYFS_BLK_PER_FILE * 2)) != MYFS_ERROR_NONE) {
			return -MYFS_ERROR_IO;
		}
    }
	else if (MYFS_IS_DIR(inode)) {      //写回目录项                    
        dentry_cur = inode->dentrys;
        offset        = MYFS_DATA_OFS(ino);
        while (dentry_cur != NULL)
        {
            memcpy(dentry_d.name, dentry_cur->fname, MYFS_MAX_FILE_NAME);
            dentry_d.ftype = dentry_cur->ftype;
            dentry_d.ino = dentry_cur->ino;
            if (newfs_driver_write(offset, (uint8_t *)&dentry_d, 
                                 sizeof(struct newfs_dentry)) != MYFS_ERROR_NONE) {
                return -MYFS_ERROR_IO;                     
            }
            
			//将该目录项指向的inode递归
            if (dentry_cur->inode != NULL) {
                newfs_sync_inode(dentry_cur->inode);
            }

            dentry_cur = dentry_cur->brother;		//它的兄弟目录项
            offset += sizeof(struct newfs_dentry);
        }
    }
     
    return MYFS_ERROR_NONE;
}
/**
 * @brief 
 * 
 * @param dentry dentry指向ino，读取该inode
 * @param ino inode编号
 * @return struct newfs_inode_m* 
 */
struct newfs_inode_m* newfs_read_inode(struct newfs_dentry_m * dentry, int ino) {
    struct newfs_inode_m* inode = (struct newfs_inode_m*)malloc(sizeof(struct newfs_inode_m));
    struct newfs_inode inode_d;
    struct newfs_dentry_m* sub_dentry;
    struct newfs_dentry dentry_d;
    int    dir_cnt = 0, i;
    if (newfs_driver_read(MYFS_INO_OFS(ino), (uint8_t *)&inode_d, 
                        sizeof(struct newfs_inode)) != MYFS_ERROR_NONE) {
        return NULL;                    
    }
    inode->dir_cnt = 0;
    inode->ino = inode_d.ino;
    inode->size = inode_d.size;
    inode->dentry = dentry;
    inode->dentrys = NULL;
    if (MYFS_IS_DIR(inode)) {			//如果是文件夹，则读入目录
        dir_cnt = inode_d.dir_cnt;
        for (i = 0; i < dir_cnt; i++)   //把读到的目录插到inode的dentrys
        {
            if (newfs_driver_read(MYFS_DATA_OFS(ino) + i * sizeof(struct newfs_dentry), 
                                (uint8_t *)&dentry_d, 
                                sizeof(struct newfs_dentry)) != MYFS_ERROR_NONE) {

                return NULL;                    
            }
            sub_dentry = new_dentry(dentry_d.name, dentry_d.ftype);
            sub_dentry->parent = dentry;		//sub_dentry在一个目录块，inode指向该目录块，dentry指向这个inode。那sub_dentry的爹就是dentry。
            sub_dentry->ino    = dentry_d.ino; 
            newfs_add_dentry(inode, sub_dentry);
        }
    }
    else if (MYFS_IS_REG(inode)) {			//如果是文件，则读入数据块
        inode->data = (uint8_t *)malloc(MYFS_BLKS_SZ(MYFS_BLK_PER_FILE * 2));
        if (newfs_driver_read(MYFS_DATA_OFS(ino), (uint8_t *)inode->data, 
                            MYFS_BLKS_SZ(MYFS_BLK_PER_FILE * 2)) != MYFS_ERROR_NONE) {
            return NULL;                    
        }
    }
    return inode;
}
/**
 * @brief 为一个inode新增一个dentry，采用头插法
 * 
 * @param inode 
 * @param dentry 
 * @return int 
 */
int newfs_add_dentry(struct newfs_inode_m* inode, struct newfs_dentry_m* dentry) {
    if (inode->dentrys == NULL) {
        inode->dentrys = dentry;
    }
    else {
        dentry->brother = inode->dentrys;
        inode->dentrys = dentry;
    }
    inode->dir_cnt++;
    return inode->dir_cnt;
}
int newfs_calc_lvl(const char * path) {

    char* str = path;
    int   lvl = 0;
	//为根目录
    if (strcmp(path, "/") == 0) {
        return lvl;
    }
    while (*str != NULL) {
        if (*str == '/') {
            lvl++;
        }
        str++;
    }
    return lvl;
}
/**
 * @brief	找到path的目录项，若找到，则返回其dentry。若没找到，则返回上一级的目录项。 
 * 
 * @param path 
 * @param is_find 是否找到
 * @param is_root 是否为根目录
 * @return newfs_dentry_m*
 */
struct newfs_dentry_m* newfs_lookup(const char * path, boolean* is_find, boolean* is_root) {
    struct newfs_dentry_m* dentry_cursor = super_m.root_dentry;
    struct newfs_dentry_m* dentry_ret = NULL;
    struct newfs_inode_m*  inode; 
    int   total_lvl = newfs_calc_lvl(path);
    int   lvl = 0;
    boolean is_hit;
    char* fname = NULL;
    char* path_cpy = (char*)malloc(sizeof(path));
    *is_root = FALSE;
    strcpy(path_cpy, path);

    if (total_lvl == 0) {                           /* 根目录 */
        *is_find = TRUE;
        *is_root = TRUE;
        dentry_ret = super_m.root_dentry;
    }
    fname = strtok(path_cpy, "/");    //strtok分割字符串   
    while (fname)
    {   
        lvl++;
        if (dentry_cursor->inode == NULL) {           //inode未被读入
            dentry_cursor->inode = newfs_read_inode(dentry_cursor, dentry_cursor->ino);
        }

        inode = dentry_cursor->inode;

        if (MYFS_IS_REG(inode) && lvl < total_lvl) {
			//该目录项的inode为文件，则返回上一级目录
            dentry_ret = inode->dentry;
            break;
        }
        if (MYFS_IS_DIR(inode)) {
            dentry_cursor = inode->dentrys;
            is_hit        = FALSE;
			//找到当前inode下文件名字与fname相同的目录项
            while (dentry_cursor)
            {	//判断名称是否相同
                if (memcmp(dentry_cursor->fname, fname, strlen(fname)) == 0) {
                    is_hit = TRUE;
                    break;
                }
                dentry_cursor = dentry_cursor->brother;
            }
            //当前文件夹下已经没任何文件（文件夹）名称和fname相同，则返回上一级dentry
            if (!is_hit) {
                *is_find = FALSE;
                // SFS_DBG("[%s] not found %s\n", __func__, fname);
                dentry_ret = inode->dentry;
                break;
            }

            if (is_hit && lvl == total_lvl) {
                *is_find = TRUE;
                dentry_ret = dentry_cursor;
                break;
            }
        }
        //若找到了fname，当深度还不够，则以dentry_cursor继续循环。
        fname = strtok(NULL, "/");  //获取分解的下一位
    }
	//若要返回的目录项的inode还没读入，则需先读入。
    if (dentry_ret->inode == NULL) {
        dentry_ret->inode = newfs_read_inode(dentry_ret, dentry_ret->ino);
    }
    
    return dentry_ret;
}
/**
 * @brief 寻找inode下的第dir_no个目录项
 * 
 * @param path 
 * @return struct newfs_inode* 
 */
struct newfs_dentry_m* newfs_get_dentry(struct newfs_inode_m * inode, int dir_no) {
    struct newfs_dentry_m* dentry_cur = inode->dentrys;
    int    cnt = 0;
    while (dentry_cur)
    {
        if (dir_no == cnt) {
            return dentry_cur;
        }
        cnt++;
        dentry_cur = dentry_cur->brother;
    }
    return NULL;
}
/******************************************************************************
* SECTION: 必做函数实现
*******************************************************************************/


/**
 * @brief 挂载（mount）文件系统
 * 
 *  Layout
 * | Super | Inode Map |Data Map|inode | Data |
 * @param conn_info 可忽略，一些建立连接相关的信息 
 * @return void*
 */
void* newfs_init(struct fuse_conn_info * conn_info) {
	/* TODO: 在这里进行挂载 */
	int                 driver_fd;
    struct newfs_super  newfs_super; 
    struct newfs_dentry_m*  root_dentry;
    struct newfs_inode_m*   root_inode;

    int                 inode_num;
	int 				inode_blks;			//估算inode会占用的磁盘块数
    int                 map_inode_blks;
    int					map_data_blks;
    int                 super_blks;
    boolean             is_init = FALSE;		//是否被初始化

	super_m.is_mounted = FALSE;
	//打开设备
	driver_fd = ddriver_open(newfs_options.device);

    if (driver_fd < 0) {
        // return driver_fd;
		return NULL;
    }
	super_m.driver_fd = driver_fd;		//把打开设备的句柄给到内存结构超级块
	//读取设备的磁盘大小,io大小,给到主存超级块
	ddriver_ioctl(MYFS_DRIVER(), IOC_REQ_DEVICE_SIZE,  &super_m.sz_disk);
    ddriver_ioctl(MYFS_DRIVER(), IOC_REQ_DEVICE_IO_SZ, &super_m.sz_io);


    // //测试读写设备
    // int offset = 528;
    // uint8_t *test_str = "shit can get!medicine,find day ,find how!sometimes I scared myself myself shit can get!";
    // uint8_t *read_str = (uint8_t *)malloc(strlen(test_str));
    // newfs_driver_write(offset,test_str,strlen(test_str));
    // newfs_driver_read(offset ,read_str,strlen(test_str));
    
	//创建根目录项
	root_dentry = new_dentry("/", NEWFS_DIR);
	//以磁盘的超级块模板读入
	if (newfs_driver_read(MYFS_SUPER_OFS, (uint8_t *)(&newfs_super),sizeof(struct newfs_super)) != MYFS_ERROR_NONE) 
	{
        // return -MYFS_ERROR_IO;
		return NULL;
    }   
	if (newfs_super.magic != MYFS_MAGIC_NUM)		//没有幻数，说明未格式化,下将计算各模块大小。
	{
		//先计算超级块要占多少个磁盘块
		super_blks = MYFS_ROUND_UP(sizeof(struct newfs_super),MYFS_IO_SZ()) / MYFS_IO_SZ();
		//估算最多有多少个inode
		inode_num  =  MYFS_DISK_SZ() / ((MYFS_BLK_PER_FILE * 2 + MYFS_INODE_PER_FILE / MYFS_INO_PER_BLK) * MYFS_IO_SZ());
		//估算inode所占的磁盘块数
		inode_blks =  inode_num / MYFS_INO_PER_BLK;
		//估算inode位图所占块数
		map_inode_blks = MYFS_ROUND_UP(MYFS_ROUND_UP(inode_num, UINT32_BITS), MYFS_IO_SZ()) 
                         / MYFS_IO_SZ();
		//估算数据块位图个数
		map_data_blks = MYFS_ROUND_UP(MYFS_ROUND_UP((2 * MYFS_BLK_PER_FILE * inode_num),UINT32_BITS),MYFS_IO_SZ())
						 / MYFS_IO_SZ(); 


		//layout
		super_m.max_ino = inode_num - (super_blks + map_inode_blks + map_data_blks)/(MYFS_INO_PER_BLK * 2);
		newfs_super.map_data_blks    = map_data_blks;
		newfs_super.map_inode_blks   = map_inode_blks;
		newfs_super.map_inode_offset = MYFS_SUPER_OFS + MYFS_BLKS_SZ(super_blks);
		newfs_super.map_data_offset  = newfs_super.map_inode_offset + MYFS_BLKS_SZ(map_inode_blks);
		newfs_super.inode_offset	 = newfs_super.map_data_offset + MYFS_BLKS_SZ(map_data_blks);
		newfs_super.data_offset 	 = newfs_super.inode_offset + MYFS_BLKS_SZ(inode_blks);
		newfs_super.sz_usage 		 =	0;


        is_init = TRUE;
	}

	//建立内存中的超级块
	super_m.sz_usage   = newfs_super.sz_usage;
		//索引节点位图
	super_m.map_inode_blks = newfs_super.map_inode_blks;
	super_m.map_inode = (uint8_t *)malloc(MYFS_BLKS_SZ(newfs_super.map_inode_blks));	//分配索引节点位图的内存
	super_m.map_inode_offset = newfs_super.map_inode_offset;
		//数据块位图
	super_m.map_data_blks = newfs_super.map_data_blks;
	super_m.map_data = (uint8_t *)malloc(MYFS_BLKS_SZ(newfs_super.map_data_blks));	//分配索引节点位图的内存
    super_m.map_data_offset = newfs_super.map_data_offset;
    //索引节点和数据块在磁盘中的偏移
	super_m.data_offset = newfs_super.data_offset;
	super_m.inode_offset = newfs_super.inode_offset;

	//读入位图
	if (newfs_driver_read(newfs_super.map_inode_offset, (uint8_t *)(super_m.map_inode), 
                        MYFS_BLKS_SZ(newfs_super.map_inode_blks)) != MYFS_ERROR_NONE) {
        // return -MYFS_ERROR_IO;
		return NULL;
    }

	if(newfs_driver_read(newfs_super.map_data_offset,(uint8_t *)(super_m.map_data),
						MYFS_BLKS_SZ(newfs_super.map_data_blks)) != MYFS_ERROR_NONE){
		// return -MYFS_ERROR_IO;
		return NULL;
	}

	//分配根目录项
	if (is_init) {                              
        root_inode = newfs_alloc_inode(root_dentry);
        newfs_sync_inode(root_inode);			//将格式化好的信息全部写回磁盘
    }

    root_inode            = newfs_read_inode(root_dentry, MYFS_ROOT_INO); 
    root_dentry->inode    = root_inode;
    super_m.root_dentry	  = root_dentry;
    super_m.is_mounted    = TRUE;

	/* 下面是一个控制设备的示例 */
	// super.fd = ddriver_open(newfs_options.device);
	
	return NULL;
}

/**
 * @brief 卸载（umount）文件系统
 * 
 * @param p 可忽略
 * @return void
 */
void newfs_destroy(void* p) {
	// /* TODO: 在这里进行卸载 */
	struct newfs_super  newfs_super_d; 
	//若还没挂载，则直接返回。
    if (!super_m.is_mounted) {		
        //  return MYFS_ERROR_NONE;
		return;
    }

    newfs_sync_inode(super_m.root_dentry->inode);     //从根节点开始同步之后的数据
    
	//将主存中超级块数据同步到磁盘的超级块
	newfs_super_d.max_ino			  = super_m.max_ino;
    newfs_super_d.magic	              = MYFS_MAGIC_NUM;
    newfs_super_d.map_inode_blks      = super_m.map_inode_blks;
    newfs_super_d.map_inode_offset    = super_m.map_inode_offset;
	newfs_super_d.map_data_blks 	  = super_m.map_data_blks;
	newfs_super_d.map_data_offset 	  = super_m.map_data_offset;
	newfs_super_d.inode_offset		  = super_m.inode_offset;
    newfs_super_d.data_offset         = super_m.data_offset;
    newfs_super_d.sz_usage            = super_m.sz_usage;
	//将超级块写回磁盘
    if (newfs_driver_write(MYFS_SUPER_OFS, (uint8_t *)&newfs_super_d, 
                      sizeof(struct newfs_super)) != MYFS_ERROR_NONE) {
        //  return -MYFS_ERROR_IO;
		return;
    }
	//写回超级块的索引块位图
    if (newfs_driver_write(newfs_super_d.map_inode_offset, (uint8_t *)(super_m.map_inode), 
                          MYFS_BLKS_SZ(newfs_super_d.map_inode_blks)) != MYFS_ERROR_NONE) {
        //  return -MYFS_ERROR_IO;
		return;
    }
	//写回超级块的数据位图
	if (newfs_driver_write(newfs_super_d.map_data_offset, (uint8_t *)(super_m.map_data), 
                          MYFS_BLKS_SZ(newfs_super_d.map_data_blks)) != MYFS_ERROR_NONE) {
        //  return -MYFS_ERROR_IO;
		return;
    }

    free(super_m.map_inode);
	free(super_m.map_data);
    ddriver_close(MYFS_DRIVER());

	// ddiver_close(super.fd);

	return;
}

/**
 * @brief 创建目录
 * 
 * @param path 相对于挂载点的路径
 * @param mode 创建模式（只读？只写？），可忽略
 * @return int 0成功，否则失败
 */
int newfs_mkdir(const char* path, mode_t mode) {
	/* TODO: 解析路径，创建目录 */
	boolean is_find, is_root;
	char* fname;
	struct newfs_dentry_m* last_dentry = newfs_lookup(path, &is_find, &is_root);
	struct newfs_dentry_m* dentry;
	struct newfs_inode_m*  inode;
    //找到了该目录，则出现错误(重复创建)
	if (is_find) {
		return -MYFS_ERROR_EXISTS;
	}
	if(MYFS_IS_REG(last_dentry->inode))
	{
		return -MYFS_ERROR_UNSUPPORTED;
	}
	char p = '/';
	fname = strrchr(path,p) + 1;		//获得名字
	dentry= new_dentry(fname,NEWFS_DIR);
	dentry -> parent = last_dentry;
	inode = newfs_alloc_inode(dentry);
	//把dentry插到inode中
	newfs_add_dentry(last_dentry->inode,dentry);
	return 0;
}

/**
 * @brief 获取文件或目录的属性，该函数非常重要
 * 
 * @param path 相对于挂载点的路径
 * @param newfs_stat 返回状态
 * @return int 0成功，否则失败
 */
int newfs_getattr(const char* path, struct stat * newfs_stat) {
	/* TODO: 解析路径，获取Inode，填充newfs_stat，可参考/fs/simplefs/sfs.c的sfs_getattr()函数实现 */
    boolean	is_find, is_root;
	struct newfs_dentry_m* dentry = newfs_lookup(path, &is_find, &is_root);
	if (is_find == FALSE) {
		return -MYFS_ERROR_NOTFOUND;
	}
    //如果是目录，则相应参数的设置
	if (MYFS_IS_DIR(dentry->inode)) {
		newfs_stat->st_mode = S_IFDIR | MYFS_DEFAULT_PERM;
		newfs_stat->st_size = dentry->inode->dir_cnt * sizeof(struct newfs_dentry);
	}
    //如果是文件，则相应参数的设置
	else if (MYFS_IS_REG(dentry->inode)) {
		newfs_stat->st_mode = S_IFREG | MYFS_DEFAULT_PERM;
		newfs_stat->st_size = dentry->inode->size;
	}

	newfs_stat->st_nlink = 1;
	newfs_stat->st_uid 	 = getuid();
	newfs_stat->st_gid 	 = getgid();
	newfs_stat->st_atime   = time(NULL);
	newfs_stat->st_mtime   = time(NULL);
	newfs_stat->st_blksize = 2 * MYFS_IO_SZ();

	if (is_root) {
		newfs_stat->st_size	= super_m.sz_usage; 
		newfs_stat->st_blocks = MYFS_DISK_SZ() / MYFS_IO_SZ();
		newfs_stat->st_nlink  = 2;		//根目录link数为2 
	}
	return MYFS_ERROR_NONE;

}

/**
 * @brief 遍历目录项，填充至buf，并交给FUSE输出
 * 
 * @param path 相对于挂载点的路径
 * @param buf 输出buffer
 * @param filler 参数讲解:
 * 
 * typedef int (*fuse_fill_dir_t) (void *buf, const char *name,
 *				const struct stat *stbuf, off_t off)
 * buf: name会被复制到buf中
 * name: dentry名字
 * stbuf: 文件状态，可忽略
 * off: 下一次offset从哪里开始，这里可以理解为第几个dentry
 * 
 * @param offset 第几个目录项
 * @param fi 可忽略
 * @return int 0成功，否则失败
 */
int newfs_readdir(const char * path, void * buf, fuse_fill_dir_t filler, off_t offset,
			    		 struct fuse_file_info * fi) {
    /* TODO: 解析路径，获取目录的Inode，并读取目录项，利用filler填充到buf，可参考/fs/simplefs/sfs.c的sfs_readdir()函数实现 */
     boolean	is_find, is_root;
	int		cur_dir = offset;

	struct newfs_dentry_m* dentry = newfs_lookup(path, &is_find, &is_root);
	struct newfs_dentry_m* sub_dentry;
	struct newfs_inode_m* inode;
	if (is_find) {
		inode = dentry->inode;
		sub_dentry = newfs_get_dentry(inode, cur_dir);
		if (sub_dentry) {
			filler(buf, sub_dentry->fname, NULL, ++offset);
		}
		return MYFS_ERROR_NONE;
	}
	return -MYFS_ERROR_NOTFOUND;

}

/**
 * @brief 创建文件
 * 
 * @param path 相对于挂载点的路径
 * @param mode 创建文件的模式，可忽略
 * @param dev 设备类型，可忽略
 * @return int 0成功，否则失败
 */
int newfs_mknod(const char* path, mode_t mode, dev_t dev) {
	/* TODO: 解析路径，并创建相应的文件 */
    boolean	is_find, is_root;
	struct newfs_dentry_m* last_dentry = newfs_lookup(path, &is_find, &is_root);
	struct newfs_dentry_m* dentry;
	struct newfs_inode_m* inode;
	char* fname;
	
	if (is_find == TRUE) {
		return -MYFS_ERROR_EXISTS;
	}
    char ch = '/';
	fname = strrchr(path, ch) + 1;
	
	if (S_ISREG(mode)) {
		dentry = new_dentry(fname, NEWFS_REG_FILE);
	}
	else if (S_ISDIR(mode)) {
		dentry = new_dentry(fname, NEWFS_DIR);
	}
	dentry->parent = last_dentry;
	inode = newfs_alloc_inode(dentry);
	newfs_add_dentry(last_dentry->inode, dentry);

	return MYFS_ERROR_NONE;
}

/**
 * @brief 修改时间，为了不让touch报错 
 * 
 * @param path 相对于挂载点的路径
 * @param tv 实践
 * @return int 0成功，否则失败
 */
int newfs_utimens(const char* path, const struct timespec tv[2]) {
	(void)path;
	return 0;
}
/******************************************************************************
* SECTION: 选做函数实现
*******************************************************************************/
/**
 * @brief 写入文件
 * 
 * @param path 相对于挂载点的路径
 * @param buf 写入的内容
 * @param size 写入的字节数
 * @param offset 相对文件的偏移
 * @param fi 可忽略
 * @return int 写入大小
 */
int newfs_write(const char* path, const char* buf, size_t size, off_t offset,
		        struct fuse_file_info* fi) {
	/* 选做 */
    boolean	is_find, is_root;
	struct newfs_dentry_m* dentry = newfs_lookup(path, &is_find, &is_root);
	struct newfs_inode_m*  inode;
	
	if (is_find == FALSE)   	return -MYFS_ERROR_NOTFOUND;
	

	inode = dentry->inode;
	
	if (MYFS_IS_DIR(inode)) 	return -MYFS_ERROR_ISDIR;	
	

	if (inode->size < offset) 	return -MYFS_ERROR_SEEK;
	

	memcpy(inode->data + offset, buf, size);
	inode->size = offset + size > inode->size ? offset + size : inode->size;
	
	return size;
}
/**
 * @brief 读取文件
 * 
 * @param path 相对于挂载点的路径
 * @param buf 读取的内容
 * @param size 读取的字节数
 * @param offset 相对文件的偏移
 * @param fi 可忽略
 * @return int 读取大小
 */
int newfs_read(const char* path, char* buf, size_t size, off_t offset,
		       struct fuse_file_info* fi) {
	/* 选做 */
    boolean	is_find, is_root;
	struct newfs_dentry_m* dentry = newfs_lookup(path, &is_find, &is_root);
	struct newfs_inode_m*  inode;

	if (is_find == FALSE) 	return -MYFS_ERROR_NOTFOUND;

	inode = dentry->inode;
	
	if (MYFS_IS_DIR(inode))	return -MYFS_ERROR_ISDIR;	
	

	if (inode->size < offset) return -MYFS_ERROR_SEEK;
	
	memcpy(buf, inode->data + offset, size);

	return size;			   			   
}

/**
 * @brief 删除文件
 * 
 * @param path 相对于挂载点的路径
 * @return int 0成功，否则失败
 */
int newfs_unlink(const char* path) {
	/* 选做 */
	return 0;
}

/**
 * @brief 删除目录
 * 
 * 一个可能的删除目录操作如下：
 * rm ./tests/mnt/j/ -r
 *  1) Step 1. rm ./tests/mnt/j/j
 *  2) Step 2. rm ./tests/mnt/j
 * 即，先删除最深层的文件，再删除目录文件本身
 * 
 * @param path 相对于挂载点的路径
 * @return int 0成功，否则失败
 */
int newfs_rmdir(const char* path) {
	/* 选做 */
	return 0;
}

/**
 * @brief 重命名文件 
 * 
 * @param from 源文件路径
 * @param to 目标文件路径
 * @return int 0成功，否则失败
 */
int newfs_rename(const char* from, const char* to) {
	/* 选做 */
	return 0;
}

/**
 * @brief 打开文件，可以在这里维护fi的信息，例如，fi->fh可以理解为一个64位指针，可以把自己想保存的数据结构
 * 保存在fh中
 * 
 * @param path 相对于挂载点的路径
 * @param fi 文件信息
 * @return int 0成功，否则失败
 */
int newfs_open(const char* path, struct fuse_file_info* fi) {
	/* 选做 */
	return 0;
}

/**
 * @brief 打开目录文件
 * 
 * @param path 相对于挂载点的路径
 * @param fi 文件信息
 * @return int 0成功，否则失败
 */
int newfs_opendir(const char* path, struct fuse_file_info* fi) {
	/* 选做 */
	return 0;
}

/**
 * @brief 改变文件大小
 * 
 * @param path 相对于挂载点的路径
 * @param offset 改变后文件大小
 * @return int 0成功，否则失败
 */
int newfs_truncate(const char* path, off_t offset) {
	/* 选做 */
    boolean	is_find, is_root;
	struct newfs_dentry_m* dentry = newfs_lookup(path, &is_find, &is_root);
	struct newfs_inode_m*  inode;
	
	if (is_find == FALSE) 	return -MYFS_ERROR_NOTFOUND;
	
	inode = dentry->inode;

	if (MYFS_IS_DIR(inode))	return -MYFS_ERROR_ISDIR;
	
    inode->size = offset;
	
	return 0;
}


/**
 * @brief 访问文件，因为读写文件时需要查看权限
 * 
 * @param path 相对于挂载点的路径
 * @param type 访问类别
 * R_OK: Test for read permission. 
 * W_OK: Test for write permission.
 * X_OK: Test for execute permission.
 * F_OK: Test for existence. 
 * 
 * @return int 0成功，否则失败
 */
int newfs_access(const char* path, int type) {
	/* 选做: 解析路径，判断是否存在 */
	return 0;
}	
/******************************************************************************
* SECTION: FUSE入口
*******************************************************************************/
int main(int argc, char **argv)
{
    int ret;
	struct fuse_args args = FUSE_ARGS_INIT(argc, argv);

	newfs_options.device = strdup("/home/guests/190110304/ddriver");

	if (fuse_opt_parse(&args, &newfs_options, option_spec, NULL) == -1)
		return -1;
	
	ret = fuse_main(args.argc, args.argv, &operations, NULL);
	fuse_opt_free_args(&args);
	return ret;
}